home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-08-10 | 7.0 KB | 296 lines | [TEXT/CWIE] |
- /*************************************************************************************
- Command.cp
-
- The command section accomplishes two things for the game -- first, providing a
- standard clock to which all actions can be synchonized, and second, grabbing the state
- of the keyboard to pass along to those game parts that need it.
-
- This code implements a time manager task that periodically grabs the state of the
- keyboard. It stores these in a buffer where the main application task can retrieve it.
-
- We create a buffer for two seconds worth of commands, although in practice we'll almost
- never need more than about a 1/10 of a second.
-
- Eventually, this code will also probably need to deal with networking tasks.
-
- Author: Timothy Carroll
- Apple Developer Technical Support
- timc@apple.com
-
- Modification History:
-
- 8/7/98 TMC Moved code over from VBL to time manager task.
- 1/26/97 TMC Now explicitly includes MoofWars.h
- 8/15/96 TMC Initial Release
-
- Copyright © 1996, 1997 Apple Computer, Inc., All Rights Reserved
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- *************************************************************************************/
-
- #include <Errors.h>
- #include <Timer.h>
-
- #include "AppConditionals.h"
- #include "Error Macros.h"
- #include "TCommandTimer.h"
-
- #if !TARGET_RT_MAC_CFM
- #error This code is not useable on classic 68K architectures.
- #endif
-
- struct CommandTimerData
- {
- TMTask fTimer;
- Boolean fRunning;
- SInt16 fFramesPerSecond;
- SInt16 fBufferSize;
- TInputState *fCommandBuffer;
- // these hold our current locations in the buffer
- SInt16 fInCommandIndex;
- SInt16 fOutCommandIndex;
- TimerUPP fCommandTimerUPP;
- SInt32 timerDelay;
- } *CommandTimerPtr;
-
- // The actual timer task that gets called to retrieve inputs.
- void CommandTimer (TMTaskPtr recPtr);
-
-
- TCommandTimer::TCommandTimer (void)
- {
- timerData = NULL;
- }
-
- TCommandTimer::~TCommandTimer (void)
- {
- if (timerData == NULL)
- return;
-
- if (timerData->fRunning)
- this->AcceptCommands(false);
-
- if (timerData->fCommandTimerUPP != NULL)
- DisposeRoutineDescriptor (timerData->fCommandTimerUPP);
-
- if (timerData->fCommandBuffer != NULL)
- DisposePtr ((Ptr) timerData->fCommandBuffer);
-
- DisposePtr ((Ptr) timerData);
- timerData = NULL;
- }
-
- OSStatus TCommandTimer::Initialize (SInt16 framesDesired)
- {
- OSStatus theErr = noErr;
-
- #if qDebugging
- if (timerData != NULL)
- SIGNAL_ERROR("\pError: TCommandTimer may only be initialized once");
- #endif
-
- // Allocate all the data structures
-
- timerData = (CommandTimerData *) NewPtrClear (sizeof (CommandTimerData));
- theErr = MemError();
- FAIL_OSERR (theErr, "\pError: Failed to allocate CommandTimerData")
-
- timerData->fFramesPerSecond = framesDesired;
- timerData->fBufferSize = 2 * timerData->fFramesPerSecond;
-
- if (framesDesired == 0) // Special case -- we're not actually using a timer!
- goto cleanup;
-
- timerData->fCommandBuffer = (TInputState *) NewPtrClear (sizeof (TInputState) * timerData->fBufferSize);
- theErr = MemError();
- FAIL_OSERR (theErr, "\pError: Failed to allocate commands buffer")
-
- timerData->fCommandTimerUPP = NewTimerProc (CommandTimer);
- if (timerData->fCommandTimerUPP == NULL)
- SIGNAL_ERROR ("\pError: Unable to allocate the timer UPP")
-
- // Set up the time manager data. We don't actually install the task until we activate the timer.
-
- timerData->fTimer.tmAddr = timerData->fCommandTimerUPP;
- //timerData->timerDelay = - (1000000/timerData->fFramesPerSecond); // amount of time per frame in microseconds
- timerData->timerDelay = 1000/timerData->fFramesPerSecond;
- goto cleanup;
-
- error:
- if (theErr == noErr)
- theErr = paramErr;
- // everything else is cleaned up by the regular destructor.
-
- cleanup:
-
- return theErr;
- }
-
-
- Boolean TCommandTimer::IsAcceptingCommands (void)
- {
- #if qDebugging
- if (timerData == NULL)
- SIGNAL_ERROR("\pError: TCommandTimer must be initialized!");
- #endif
-
- if (timerData->fFramesPerSecond == 0)
- return true;
-
- return timerData->fRunning;
-
- error:
-
- return false;
-
- }
-
- void TCommandTimer::AcceptCommands (Boolean commands)
- {
- #if qDebugging
- if (timerData == NULL)
- SIGNAL_ERROR("\pError: TCommandTimer must be initialized!");
- #endif
-
- if (timerData->fFramesPerSecond == 0)
- {
- return;
- }
-
- if (timerData->fRunning == commands)
- return;
-
-
- if (commands)
- {
- timerData->fRunning = true;
- // tn1063 documents that we need to clear these fields to make sure nothing wacky happens.
- timerData->fTimer.qLink = NULL;
- timerData->fTimer.tmReserved = 0;
- InsXTime ((QElemPtr) &timerData->fTimer);
- PrimeTime ((QElemPtr) &timerData->fTimer, timerData->timerDelay);
- }
- else
- {
- timerData->fRunning = false;
- RmvTime((QElemPtr) &timerData->fTimer);
- }
-
- error:
- return;
- }
-
- void TCommandTimer::FlushCommands(void)
- {
- #if qDebugging
- if (timerData == NULL)
- SIGNAL_ERROR("\pError: TCommandTimer must be initialized!");
-
- if (timerData->fRunning)
- SIGNAL_ERROR ("\pError: TCommandTimer must not be accepting commands");
- #endif
-
- if (timerData->fFramesPerSecond == 0)
- {
- return;
- }
-
- timerData-> fInCommandIndex = timerData->fOutCommandIndex = 0;
- error:
- return;
- }
-
- Boolean TCommandTimer::IsCommandWaiting (void)
- {
- #if qDebugging
- if (timerData == NULL)
- SIGNAL_ERROR("\pError: TCommandTimer must be initialized!");
- #endif
-
- if (timerData->fFramesPerSecond == 0)
- {
- return true;
- }
-
- if (timerData->fInCommandIndex != timerData->fOutCommandIndex)
- return true;
- error:
- return false;
- }
-
- Boolean TCommandTimer::RetrieveCommand (TInputState *command)
- {
- Boolean peek;
-
- if (timerData->fFramesPerSecond == 0)
- {
- GetKeys (command->keys);
- return true;
- }
-
- peek = this->PeekCommand (command);
-
- if (peek)
- timerData->fOutCommandIndex = (timerData->fOutCommandIndex +1) % (timerData->fBufferSize);
-
- return peek;
-
- }
-
- Boolean TCommandTimer::PeekCommand (TInputState *command)
- {
- SInt16 index;
-
- #if qDebugging
- if (timerData == NULL)
- SIGNAL_ERROR("\pError: TCommandTimer must be initialized!");
- #endif
-
- if (timerData->fFramesPerSecond == 0)
- {
- GetKeys (command->keys);
- return true;
- }
-
- if (timerData->fInCommandIndex == timerData->fOutCommandIndex)
- return false;
-
- index = (timerData->fOutCommandIndex +1) % (timerData->fBufferSize);
- *command = (timerData->fCommandBuffer)[index];
-
- return true;
-
- error:
- return false;
- }
-
-
- void CommandTimer (TMTaskPtr recPtr)
- {
- CommandTimerData *timerData = (CommandTimerData *) recPtr;
- SInt16 index;
-
- if (!timerData->fRunning)
- return;
-
- index = (timerData->fInCommandIndex+1) % timerData->fBufferSize;
-
- if (index != timerData->fOutCommandIndex)
- {
- timerData->fInCommandIndex = index;
- GetKeys (((timerData->fCommandBuffer)[index]).keys);
- }
-
- // Reset the timer
-
- PrimeTime((QElemPtr) &timerData->fTimer, timerData->timerDelay);
-
- }
-